home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / tipmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-30  |  10.0 KB  |  441 lines

  1. /* "Dumb terminal" mailbox interface
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  *    May '91 Bill Simpson
  5.  *        move to separate file for compilation & linking
  6.  *    Sep '91 Bill Simpson
  7.  *        minor changes for DTR & RLSD
  8.  *      Jan '93 Doug Crompton
  9.  *              Mods to code to make it work with both terminal
  10.  *              and Modem. Timers and CD check revamped. Now Always
  11.  *              detects CD loss and timeouts work properly.
  12.  *              Setting Tiptimeout to 0 disables idle and CD loss check
  13.  *
  14.  *              Command Syntax now : 'start tip <interface> <modem|terminal>'
  15.  */
  16. #include "global.h"
  17. #include "config.h"
  18. #include "mbuf.h"
  19. #include "timer.h"
  20. #include "proc.h"
  21. #include "iface.h"
  22. #ifndef UNIX
  23. #include "i8250.h"
  24. #endif
  25. #include "asy.h"
  26. #include "socket.h"
  27. #include "usock.h"
  28. #include "telnet.h"
  29. #include "mailbox.h"
  30. #include "tipmail.h"
  31. #include "devparam.h"
  32.  
  33. #ifdef TIPMAIL
  34. #ifdef ALLSERV
  35.  
  36. static void tip_in __ARGS((int dev,void *n1,void *n2));
  37. static void tipidle __ARGS((void *t));
  38.  
  39. unsigned Tiptimeout = 180;    /* Default tip inactivity timeout (seconds) */
  40.  
  41. struct suspended {
  42.     struct iface *ifp;
  43.     unsigned timeout;
  44.     char modem;
  45. } Tipsuspended[ASY_MAX];
  46.  
  47. /* Input process */
  48. static void
  49. tip_in(dev,n1,n2)
  50. int dev;
  51. void *n1,*n2;
  52. {
  53.     struct tipcb *tip;
  54.     struct mbuf *bp;
  55.     char *buf[2], line[MBXLINE];
  56.     int c, ret, pos = 0;
  57.  
  58.     tip = (struct tipcb *) n1;
  59.     while((c = get_asy(dev)) != -1){
  60.         tip->firstwarn=1;
  61.         tip->timeout=tip->default_timeout;
  62.         Asy[dev].iface->lastrecv = secclock();
  63.  
  64.         if (!tip->raw) {                  
  65.             c &= 0x7f;
  66.             ret = 0;
  67.             if(tip->echo == WONT){
  68.                 switch(c){
  69.                 case 18:    /* CTRL-R */
  70.                     bp = pushdown(qdata(line,pos),4);
  71. #ifndef TNOS_68K
  72.                     memcpy(bp->data,"^R\r\n",4);
  73. #else
  74.                     memcpy(bp->data,"^R\r\l",4);
  75. #endif
  76.                     ret = 1;
  77.                     break;
  78.                 case 0x7f:    /* DEL */
  79.                 case '\b':
  80.                     bp = NULLBUF;
  81.                     if(pos){
  82.                         --pos;
  83.                         bp = qdata("\b \b",3);
  84.                     }
  85.                     ret = 1;
  86.                     break;
  87. #ifndef TNOS_68K
  88.                 case '\r':
  89. #else
  90.                 case '\l':
  91. #endif
  92.                     c = '\n';       /* CR => NL */
  93.                 case '\n':
  94. #ifndef TNOS_68K
  95.                     bp = qdata("\r\n",2);
  96. #else
  97.                     bp = qdata("\r\l",2);
  98. #endif
  99.                     break;
  100.                 default:
  101.                     bp = pushdown(NULLBUF,1);
  102.                     *bp->data = c;
  103.                     break;
  104.                 }
  105.                 asy_send(dev,bp);
  106.                 tip->iface->lastsent = secclock();
  107.                 if(ret)
  108.                     continue;
  109.             }
  110.             line[pos++] = c;
  111.             if(pos == MBXLINE - 1 || tip->echo == WILL
  112.               || c == '\n'){
  113.                 line[pos] = '\0';
  114.                 pos = 0;
  115.                 usputs(tip->s,line);
  116.                 usflush(tip->s);
  117.             }
  118.         } else {
  119.             usputc(tip->s,c);
  120.             usflush(tip->s);
  121.         }
  122.     }
  123.     /* get_asy() failed, terminate */
  124.     close_s(tip->s);
  125.     tip->in = tip->proc;
  126.     tip->proc = Curproc;
  127.     buf[1] = Asy[dev].iface->name;
  128.     tip0(2,buf,NULL);
  129. }
  130. /* Start mailbox on serial line */
  131. int
  132. tipstart(argc,argv,p)
  133. int argc;
  134. char *argv[];
  135. void *p;
  136. {
  137.     register struct iface *ifp;
  138.     register struct asy *ap;
  139.     register struct tipcb *tip;
  140.     struct mbuf *bp, *dp, *op; /* op is output, dp is duplicate */
  141.     struct fifo *fp; 
  142.     char *buf[2];
  143.     int dev, c, i, off, cnt, cmd, s[2], type = TIP;
  144.  
  145.     if((ifp = if_lookup(argv[1])) == NULLIF){
  146.     tprintf(Badinterface,argv[1]);
  147.         return 1;
  148.     }
  149.     for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  150.         if(ap->iface == ifp)
  151.             break;
  152.     if(dev == ASY_MAX){
  153.         tprintf("Interface %s not asy port\n",argv[1]);
  154.         return 1;
  155.     }
  156.     if(ifp->raw == bitbucket){
  157.         tprintf("Tip session already active on %s\n",argv[1]);
  158.         return 1;
  159.     }
  160.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  161.     chname(Curproc,"Mbox tip");
  162.     tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
  163.  
  164.     if (argc > 2 && *argv[2] == 'm')
  165.         tip->modem = 1;
  166.     tprintf("Tip started on %s -  with%s CD check - ",argv[1], (tip->modem) ? "" : "out");
  167.     tip->default_timeout = (argc > 3) ? atoi(argv[3]) : Tiptimeout;    
  168.     if (tip->default_timeout)
  169.         tprintf("%d Second",tip->default_timeout);
  170.     else
  171.         tprintf("No");
  172.     tprintf(" Timeout\n");
  173.  
  174.  
  175.     /* Save output handler and temporarily redirect output to null */
  176.     tip->asy_dev=dev;
  177.     tip->rawsave = ifp->raw;
  178.     ifp->raw = bitbucket;
  179.     tip->iface = ifp;
  180.     tip->proc = Curproc;
  181.     tip->timer.func = tipidle;
  182.     tip->timer.arg = (void *) tip;
  183.     tip->raw=0;
  184.     tip->next = Tiplist;
  185.     Tiplist = tip;
  186.     buf[1] = ifp->name;
  187.  
  188.     /* Suspend packet input drivers */
  189.     suspend(ifp->rxproc);
  190.  
  191.     for(;;) {
  192.         ifp->ioctl(ifp,PARAM_UP,TRUE,0L);
  193.         /* Wait for DCD to be asserted if modem */
  194.         if (tip->modem)        {
  195.             mspause (1000);
  196.             while (! carrier_detect(tip->asy_dev))
  197.                 pwait(NULL);
  198.             mspause(1000L);
  199.         }
  200.  
  201.         if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  202.             tprintf("Could not create socket pair, errno %d\n",errno);
  203.             tip0(2,buf,p);
  204.             return 1;
  205.         }
  206.         seteol(s[0],"\n");
  207.         seteol(s[1],"\n");
  208.         tip->echo = WONT;
  209.         tip->s = s[0];
  210.         if (tip->modem)
  211.             log(tip->s,"Phone Mailbox Login");
  212.         newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,(void *)tip,0);
  213.  
  214.         /* check for line idle timeout and CD failure */
  215.         tip->firstwarn=1;
  216.         tip->timeout=tip->default_timeout;
  217.         set_timer(&tip->timer,1000L);
  218.         start_timer(&tip->timer);
  219.  
  220.         setflush(tip->s,-1);
  221.         sockmode(tip->s,SOCK_ASCII);
  222.  
  223.         /* Now fork into two paths, one rx, one tx */
  224.         /* first clear (ignore) junk in asyinc input
  225.            which is always receiving - modem can garbage
  226.            on disconnect
  227.         */
  228.         fp = &ap->fifo;
  229.         fp->wp = fp->rp = fp->buf;
  230.         fp->cnt = 0;
  231.         
  232.         tip->in = newproc("Mbox tip in",
  233.                 256,tip_in,dev,(void *)tip,NULL,0);
  234.         while((cnt = recv_mbuf(tip->s,&bp,0,NULL,0)) != -1) {
  235.            if(!tip->raw) {     
  236.             dup_p(&dp,bp,off=0,cnt); /* dup the whole pkt to pull */
  237.             for (i=0; i<cnt; i++)
  238.                switch(PULLCHAR(&dp)) {
  239.                case IAC:      /* ignore most telnet options */
  240.                   dup_p(&op,bp,off,i-off);
  241.                   asy_send(dev,op);
  242.                   ifp->lastsent = secclock();
  243.  
  244.                   if((cmd = ++i < cnt ?  PULLCHAR(&dp) :
  245.                      recvchar(tip->s)) == -1)
  246.                      break;
  247.                   if(cmd > 250 && cmd < 255) {
  248.                       if((c = ++i < cnt ? PULLCHAR(&dp) :
  249.                           recvchar(tip->s)) == -1)
  250.                           break;
  251.                       switch(cmd){
  252.                       case WILL:
  253.                           if(c == TN_ECHO) {
  254.                               tip->echo = cmd;
  255.                               cmd = DO;
  256.                           }
  257.                           else
  258.                               cmd = DONT;
  259.                           break;
  260.                       case WONT:
  261.                           if(c == TN_ECHO)
  262.                               tip->echo = cmd;
  263.                           cmd = DONT;
  264.                           break;
  265.                       case DO:
  266.                       case DONT:
  267.                           cmd = WONT;
  268.                           break;
  269.                       }
  270.                       usprintf(tip->s,"%c%c%c",IAC,cmd,c);
  271.                       usflush(tip->s);
  272.                   }
  273.                   off = i + 1;
  274.                   break;
  275.             case '\r':
  276.                   if ( ++i < cnt &&  /* Skip NL but not IAC */
  277.                       (PULLCHAR(&dp) == IAC)) {
  278.                     dp = pushdown(dp,1);
  279.                     *dp->data = IAC;
  280.                     }
  281.                   break;
  282. #ifndef TNOS_68K
  283.             case '\n':
  284. #else
  285.             case '\l':
  286. #endif
  287.                   dup_p(&op,bp,off,i-off);
  288. #ifndef TNOS_68K
  289.                   append(&op,qdata("\r\n",2));
  290. #else
  291.                   append(&op,qdata("\r\l",2));
  292. #endif
  293.                   asy_send(dev,op);
  294.                   ifp->lastsent = secclock();
  295.                   off = i + 1;
  296.                   break;
  297.              }
  298.  
  299.             (void)pullup(&bp,NULLBUF,off);
  300.             asy_send(dev,bp);
  301.              } else {
  302.             asy_send(dev,bp);
  303.              }
  304.              ifp->lastsent = secclock();
  305.  
  306.              pwait(NULL);
  307.         }
  308.         stop_timer(&tip->timer);
  309.         mspause(2000L);
  310.         close_s(tip->s);
  311.         killproc(tip->in);
  312.         tip->in = NULLPROC;
  313.  
  314.         pwait(itop(s[1])); /* let mailbox terminate, if necessary */
  315.  
  316.         if (!tip->keep && tip->modem)    {
  317.             /* Tell line to go down */
  318.             ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  319.             mspause (5000);
  320.         }
  321.     }
  322. }
  323. int
  324. tip0(argc,argv,p)
  325. int argc;
  326. char *argv[];
  327. void *p;
  328. {
  329.     register struct iface *ifp;
  330.     struct tipcb *tip, *prev = NULLTIP;
  331.     struct proc *proc;
  332.  
  333.     if((ifp = if_lookup(argv[1])) == NULLIF){
  334.     tprintf(Badinterface,argv[1]);
  335.         return 1;
  336.     }
  337.     for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  338.         if(tip->iface == ifp) {
  339.             if(prev != NULLTIP)
  340.                 prev->next = tip->next;
  341.             else
  342.                 Tiplist = tip->next;
  343.             proc = tip->proc;
  344.             close_s(tip->s);
  345.             ifp->raw = tip->rawsave;
  346.             resume(ifp->rxproc);
  347.             stop_timer(&tip->timer);
  348.             killproc(tip->in);
  349.             free((char *)tip);
  350.             killproc(proc);
  351.             return 0;
  352.         }
  353.     return 0;
  354. }
  355. static void
  356. tipidle(t)
  357. void *t;
  358. {
  359.     struct tipcb *tip;
  360. #ifndef TNOS_68K
  361.     static char *msg1 = "Line idle - One minute to disconnect...\007\r\n";
  362.     static char *msg2 = "Disconnecting...\007\r\n";
  363. #else
  364.     static char *msg1 = "Line idle - One minute to disconnect...\007\r\l";
  365.     static char *msg2 = "Disconnecting...\007\r\l";
  366. #endif
  367.     tip = (struct tipcb *) t;
  368.  
  369.     if (tip->modem && ! carrier_detect(tip->asy_dev)) {
  370.           close_s(tip->s);
  371.           return;
  372.     }
  373.     
  374.     if (tip->default_timeout && --tip->timeout <= 0) {
  375.           if (tip->firstwarn) {
  376.           tip->iface->lastsent = secclock();
  377.           asy_send(tip->iface->dev,qdata(msg1,strlen(msg1)));
  378.           tip->timeout=60;
  379.           start_timer(&tip->timer);
  380.           tip->firstwarn=0;
  381.           } else {
  382.           asy_send(tip->iface->dev,qdata(msg2,strlen(msg2)));
  383.           close_s(tip->s);
  384.           }
  385.     } else {
  386.           start_timer(&tip->timer);
  387.     }
  388. }
  389.  
  390.  
  391.  
  392.  
  393. void
  394. suspendTipMail(m)
  395. struct mbx *m;
  396. {
  397. char *args[2];
  398. register int k;
  399. register struct tipcb *tip;
  400.  
  401.     if (m->tip->modem)        {    /* if modem connect, we can resume */
  402.         /* save the interface in the suspended array, for asytimer() */
  403.         Tipsuspended[m->tip->asy_dev].ifp = m->tip->iface;
  404.         Tipsuspended[m->tip->asy_dev].modem = m->tip->modem;
  405.         Tipsuspended[m->tip->asy_dev].timeout = m->tip->default_timeout;
  406.         m->tip->keep = 1;
  407.         tputs ("Tipmail will resume after you disconnect\n");
  408.     } else
  409.         tputs ("Tipmail terminated on this interface\n");
  410.     usflush (Curproc->output);
  411.     /* now stop the tipmail */
  412.     args[1] = m->tip->iface->name;
  413.     tip0 (2, args, NULL);
  414. }
  415. #endif /*ALLSERV*/
  416. #endif /* TIPMAIL */
  417.  
  418. static int Stelnet = -1;
  419.  
  420. /* Start up Telnet server */
  421. int
  422. telnet1(argc,argv,p)
  423. int argc;
  424. char *argv[];
  425. void *p;
  426. {
  427.     return (installserver (argc, argv, &Stelnet, "Telnet listener", IPPORT_TELNET,
  428.         "mbox", mbx_incom,2048, (void *)TELNET_LINK));
  429. }
  430. /* Stop telnet server */
  431. int
  432. telnet0(argc,argv,p)
  433. int argc;
  434. char *argv[];
  435. void *p;
  436. {
  437.     return (deleteserver (&Stelnet));
  438. }
  439.  
  440.  
  441.